const Notice = require('../models/Notice');
const Group = require('../models/Group');
const { StatusCodes } = require('http-status-codes');
const mongoose = require('mongoose');
const _ = require('lodash');
const { getNoticeInfo } = require('../utils/doc');

const getNoticeQuery = (userId) => ({
   $or: [
      {
         sender: userId,
         type: {
            $nin: [
               'RECEIVE_INVITATION',
               'INFORMED_ACCEPT_INVITATION',
               'INFORMED_REJECT_INVITATION',
               'INFORMED_SOMEONE_JOIN_BY_INVITATION_CODE',
            ],
         },
      },
      { receiver: userId },
   ],
});
/**
 * 获取通知
 */
const getNotices = async (req, res) => {
   const userId = mongoose.Types.ObjectId(req.user.userId);
   // 作为发送者 只关注接受者拒绝或同意；
   const notices = await Notice.find(getNoticeQuery(userId))
      .populate({
         path: 'receiver',
         model: 'User',
         select: 'username',
      })
      .populate({
         path: 'receivers',
         model: 'User',
         select: 'username',
      })
      .populate({
         path: 'group',
         model: 'Group',
         select: 'group_name',
      })
      .populate({
         path: 'sender',
         model: 'User',
         select: 'username',
      })
      .sort({ createdAt: -1 });

   const list = notices.map((item) => {
      const { _id, type, group, receivers, sender, createdAt, status } = item;

      const groupName = (group && group.group_name) || '<该组织已被删除>';
      let obj = {
         _id,
         type,
         createdAt,
         groupName, // 用于替换样式
         status,
         msg: '',
      };
      switch (type) {
         case 'SEND_INVITATION':
            obj.msg = `你邀请了${receivers
               .map((user) => user.username)
               .join('、')}加入${groupName}。`;
            break;
         case 'RECEIVE_INVITATION':
            obj.msg = `${sender.username}邀请你加入${groupName}。`;
            break;
         case 'INFORMED_ACCEPT_INVITATION':
         case 'INFORMED_SOMEONE_JOIN_BY_INVITATION_CODE':
            obj.msg = `${sender.username}成功加入${groupName}。`;
            break;
         case 'INFORMED_REJECT_INVITATION':
            obj.msg = `${sender.username}拒绝加入${groupName}。`;
            break;
         case 'ACCEPT_INVITATION':
         case 'JOIN_BY_INVITATION_CODE':
            obj.msg = `你成功加入了${groupName}。`;
            break;
         case 'REJECT_INVITATION':
            obj.msg = `你拒绝加入${groupName}。`;
            break;
         case 'KICK_OUT_MEMBER':
            obj.msg = `你将${receivers
               .map((user) => user.username)
               .join('、')}踢出${groupName}。`;
            break;
         case 'INFORMED_KICK_OUT_MEMBER':
            obj.msg = `你被踢出${groupName}。`;
            break;

         default:
            obj.msg = `未定义。`;
            break;
      }
      return obj;
   });

   res.status(StatusCodes.OK).json({ list });
};

/**
 * 更新已读状态
 */
const updateRead = async (req, res) => {
   const noticeId = mongoose.Types.ObjectId(req.body.noticeId);
   await Notice.findByIdAndUpdate(noticeId, {
      status: 'read',
   });
   res.status(StatusCodes.OK).json({ msg: '更新成功' });
};

// 拒绝邀请
const rejectInvitation = async (req, res) => {
   const noticeId = mongoose.Types.ObjectId(req.body.noticeId);
   const notice = await getNoticeInfo(noticeId);

   // 先删除掉原来的邀请
   await Notice.deleteOne({ _id: noticeId, type: 'RECEIVE_INVITATION' });
   await Notice.insertMany([
      // 1. 自己拒绝的记录（给自己看的）
      {
         type: 'REJECT_INVITATION',
         group: notice.group._id,
         receiver: req.user.userId,
         status: 'read',
      },
      // 2. 给别人反馈（给别人看的）
      {
         type: 'INFORMED_REJECT_INVITATION',
         group: notice.group._id,
         receiver: notice.sender._id,
         sender: req.user.userId,
      },
   ]);
   res.status(StatusCodes.OK).json({ msg: '已拒绝' });
};

// 同意邀请
const acceptInvitation = async (req, res) => {
   const noticeId = mongoose.Types.ObjectId(req.body.noticeId);
   const notice = await getNoticeInfo(noticeId);

   const session = await mongoose.startSession();
   session.startTransaction();

   try {
      // 先删除掉原来的
      await Notice.deleteOne({ _id: noticeId, type: 'RECEIVE_INVITATION' });
      await Notice.insertMany(
         [
            // 1. 自己接受的记录（给自己看的）
            {
               type: 'ACCEPT_INVITATION',
               group: notice.group._id,
               receiver: req.user.userId,
               status: 'read',
            },
            // 2. 给别人反馈（给别人看的）
            {
               type: 'INFORMED_ACCEPT_INVITATION',
               group: notice.group._id,
               receiver: notice.sender._id,
               sender: req.user.userId,
            },
         ],
         {
            runValidators: true,
         }
      );

      // 2. 寻找对应的分组，加入该成员
      await Group.findByIdAndUpdate(mongoose.Types.ObjectId(notice.group._id), {
         $push: { members: req.user.userId },
      });
      await session.commitTransaction();
      res.status(StatusCodes.OK).json({ msg: '成功加入组织' });
   } catch (err) {
      await session.abortTransaction();
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: err });
   } finally {
      session.endSession();
   }
};

/**
 * 删除通知
 */
const deleteNotices = async (req, res) => {
   const ids = req.body.ids;
   if (!ids || ids.length === 0)
      res.status(StatusCodes.BAD_REQUEST).json({ msg: '请传入通知的id' });
   await Notice.deleteMany({ _id: { $in: ids } });
   res.status(StatusCodes.OK).json({ msg: '删除成功' });
};

// 判断是否有未读通知
const getIsNew = async (req, res) => {
   const userId = mongoose.Types.ObjectId(req.user.userId);
   const notices = await Notice.find(getNoticeQuery(userId)).select('status');
   const isNew = notices.some((item) => item.status === 'unread');
   res.status(StatusCodes.OK).json({
      msg: 'ok',
      data: {
         isNew,
      },
   });
};

module.exports = {
   getNotices,
   deleteNotices,
   updateRead,
   rejectInvitation,
   acceptInvitation,
   getIsNew,
};
